#include "tools/Pyscript.h"
#include "tools/Reader.h"
#include "tools/Gadget.h"
//#========================================模块寻找错误，为空，初始化值为1：-> 脚本语法错误/pro文件依赖不全或有错


const char* PPScriptExec::PyScript_ExtraTostr(PyObject *resource){
    char *it;
    PyArg_Parse(resource, "s", &it);
    return it;
}


bool PPScriptExec::PyScript_ExtraTobool(PyObject *resource){
    bool it;
    PyArg_Parse(resource, "b", &it);
    return it;
}


QStringList PPScriptExec::PyScript_ExtraAnststr(PyObject *resource){
    QStringList L;
    PyScript_ExtraToststr(L, resource);
    return L;
}


QStringList &PPScriptExec::PyScript_ExtraToststr(QStringList &MangList, PyObject *resource){
    QStringList SectionList;
    PyObject *item=nullptr;
    int RunInt = PyObject_Size(resource);
    if (RunInt > 0){
        for (int i = 0; i < RunInt ; i++){
            if (PyList_Check(resource)){
                item = PyList_GetItem(resource, i);
            } else {
                item = PyTuple_GetItem(resource, i);
            }

            if (PyList_Check(item) || PyTuple_Check(item)){
                PyScript_ExtraToststr(MangList, item);
            } else {
                const char *cvc;
                PyArg_Parse(item, "s", &cvc);
                SectionList << QString(cvc);
            }
        }
        MangList << SectionList;
    }

    return MangList;
}


PyObject* PPScriptExec::PyScript_CreateTodict(QMap<QString, QString> &Map){
    PyObject *Dict = PyDict_New();
    QStringList k = Map.keys();
    QStringList v = Map.values();
    QString c_key = k[0];
    QString c_value = v[0];
    PyObject *key = Py_BuildValue("s", c_key.toStdString().c_str());
    PyObject *value = Py_BuildValue("s", c_value.toStdString().c_str());
    Py_INCREF(c_key.toStdString().c_str());
    Py_INCREF(c_value.toStdString().c_str());
    PyDict_SetItem(Dict, key, value);
    return Dict;
}


std::pair<QStringList, QMap<QString, QStringList>> PPScriptExec::PyScript_ExtraAnststrm(PyObject *resource){
    QMap<QString, QStringList> PushMap;
    QStringList Keys = PyScript_ExtraAnststr(PyDict_Keys(resource));
    foreach(QString key, Keys){
        PushMap[key] = PyScript_ExtraAnststr(PyDict_GetItemString(resource, key.toStdString().c_str()));
    }

    return std::make_pair(Keys, PushMap);
}


std::pair<QStringList, QMap<QString, QString>> PPScriptExec::PyScript_ExtraTostrm(PyObject *resource){
    QMap<QString, QString> PushMap;
    QStringList Keys = PyScript_ExtraAnststr(PyDict_Keys(resource));
    foreach(QString key, Keys)
    {
        PushMap[key] = PyScript_ExtraTostr(PyDict_GetItemString(resource, key.toStdString().c_str()));
    }

    return std::make_pair(Keys, PushMap);
}


std::pair<QStringList, QMap<QString, QStringList>> PPScriptExec::PyScript_WingsGet(const char *_module, const char *_modulePath, const char *_func, QStringList Columns){
    PPScriptExec();
    std::pair<QStringList, QMap<QString, QStringList>> Xlwings;
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    Py_ssize_t Csize = Columns.size();
    PyObject *ColArg = PyTuple_New(Csize);
    PyObject *py_tuple = PyTuple_New(2);
    for (int sz = 0; sz < Csize; sz++){
        PyTuple_SetItem(ColArg, sz, Py_BuildValue("s", Columns[sz].toStdString().c_str()));
    }
    PyTuple_SetItem(py_tuple, 0, Py_BuildValue("s", _modulePath));
    PyTuple_SetItem(py_tuple, 1, ColArg);
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {
                return PyScript_ExtraAnststrm(py_runningrs);
            }
        }
        else
        {

        }
    }
    return Xlwings;
}


void PPScriptExec::PyScript_MediainfoGet(const char *_module, const char *_func, const char *_mediaPath, QMap<QString, QString> &get){
    PPScriptExec();
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    qDebug() << !py_module;
    PyObject *py_tuple = PyTuple_New(1);
    PyTuple_SetItem(py_tuple, 0, Py_BuildValue("s", _mediaPath));
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {
                get = PyScript_ExtraTostrm(py_runningrs).second;
            }
            Py_XDECREF(py_runningrs);
        }
        Py_XDECREF(py_function);
    }
    Py_XDECREF(py_module);
}


QString PPScriptExec::PyScript_UnitTchz(const char *_module, const char *_func, const char *_string, QString &get){
    PPScriptExec();
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    PyObject *py_tuple = PyTuple_New(1);
    PyTuple_SetItem(py_tuple, 0, Py_BuildValue("s", _string));
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {
                get = PyScript_ExtraTostr(py_runningrs);
                Py_XDECREF(py_runningrs);
            }
            Py_XDECREF(py_function);
        }
    }
    Py_XDECREF(py_module);
    Py_XDECREF(py_tuple);
    return QString();
}


bool PPScriptExec::PyScript_AssertReply(const char *_module, const char *_func, const char *_requestPath, QMap<QString, QString> &_requestHead){
    bool RequestStat = false;
    PPScriptExec();
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    PyObject *py_tuple = PyTuple_New(1);
    PyObject *headers = PyScript_CreateTodict(_requestHead);
    PyTuple_SetItem(py_tuple, 0, Py_BuildValue("s", _requestPath));
    PyTuple_SetItem(py_tuple, 1, headers);
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {
                RequestStat = PyScript_ExtraTobool(py_runningrs);
                Py_XDECREF(py_runningrs);
            }
            Py_XDECREF(py_function);
        }
    }
    if (headers) Py_XDECREF (py_module);
    if (headers) Py_XDECREF (py_tuple);
    if (py_tuple) Py_XDECREF (headers);
    return RequestStat;
}


void PPScriptExec::pyScript_ImageByteDressMaker(const char *_module, const char *_func, const char *_file, QList<qint64> &_sxpsize, QList<qint64> &_cropsize, QString &bytestr){
    PPScriptExec();
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    QByteArray byteArray64 = Extend().getImgbyte(_file);
    PyObject *py_byte = PyBytes_FromString(byteArray64.data());
    PyObject *expssli = PyTuple_New(2);
    PyObject *exprecli = PyTuple_New(4);
    for(int i = 0; i < _sxpsize.size(); i++) PyTuple_SetItem(expssli, i, Py_BuildValue("i", _sxpsize[i]));
    for(int i = 0; i < _cropsize.size(); i++) PyTuple_SetItem(exprecli, i, Py_BuildValue("i", _cropsize[i]));
    PyObject *py_tuple = PyTuple_New(3);
    PyTuple_SetItem(py_tuple, 0, py_byte);
    PyTuple_SetItem(py_tuple, 1, expssli);
    PyTuple_SetItem(py_tuple, 2, exprecli);
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {
                PyObject *PyResultString = PyObject_Repr(py_runningrs);
                const char *ResultString = PyUnicode_AsUTF8(PyResultString);
                bytestr = QRegularExpression("\'.*\'").match(ResultString).captured(0);
                Py_XDECREF(PyResultString);
            }
            Py_XDECREF(py_function);
        }
    }
    Py_XDECREF(py_module);
    Py_XDECREF(py_byte);
    Py_XDECREF(expssli);
    Py_XDECREF (exprecli);
}


void PPScriptExec::pyScript_PilrsizeforPixmap(const char *_module, const char *_func, QPixmap &pixmap, QList<int> size){
    PPScriptExec();
    QString byteString=NULL;
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    QByteArray byteArray = Extend().getImgbyte(pixmap);
    QByteArray byteArray64 = QByteArray::fromBase64(byteArray).toBase64();
    PyObject *py_byte = PyBytes_FromString(byteArray64);
    PyObject *sizeList = PyTuple_New(2);
    PyObject *py_tuple = PyTuple_New(2);
    for(int i = 0; i < size.size(); i++) PyTuple_SetItem(sizeList, i, Py_BuildValue("i", size[i]));
    PyTuple_SetItem(py_tuple, 0, py_byte);
    PyTuple_SetItem(py_tuple, 1, sizeList);
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {
                PyObject *PyResultString = PyObject_Repr(py_runningrs);
                const char *ResultString = PyUnicode_AsUTF8(PyResultString);
                byteString = QRegularExpression("\'.*\'").match(ResultString).captured(0);
                pixmap.loadFromData(QByteArray::fromBase64(byteString.toLocal8Bit()));
                Py_XDECREF(py_runningrs);
            }
            Py_XDECREF(py_function);
        }
    }
    if (py_byte) Py_XDECREF (py_byte);
    if (sizeList) Py_XDECREF (sizeList);
    if (py_tuple) Py_XDECREF (py_tuple);
}


void PPScriptExec::pyScript_QrcodeByte(const char *_module, const char *_func, const char *_qrdata, QPixmap &pixmap, const char *_savePath,
                                       const char *_fore, const char *_back, uint _borderxp, uint _sizertxp){
    PPScriptExec();
    PyObject *py_module = PyImport_ImportModuleLevel(_module, nullptr, nullptr, NULL, 0);
    PyObject *py_tuple = PyTuple_New(6);
    PyTuple_SetItem(py_tuple, 0, Py_BuildValue("s", _qrdata));
    PyTuple_SetItem(py_tuple, 1, Py_BuildValue("s", _savePath));
    PyTuple_SetItem(py_tuple, 2, Py_BuildValue("s", _fore));
    PyTuple_SetItem(py_tuple, 3, Py_BuildValue("s", _back));
    PyTuple_SetItem(py_tuple, 4, Py_BuildValue("i", _borderxp));
    PyTuple_SetItem(py_tuple, 5, Py_BuildValue("i", _sizertxp));
    if (py_module)
    {
        PyObject *py_function = PyObject_GetAttrString(py_module, _func);
        bool py_valid = PyCallable_Check(py_function);
        if (py_valid)
        {
            PyObject *py_runningrs = PyObject_CallObject(py_function, py_tuple);
            if (py_runningrs)
            {                
                char *it;
                PyArg_Parse(py_runningrs, "s", &it);
                QString bytechar = it;
                pixmap.loadFromData(QByteArray::fromBase64(bytechar.toLocal8Bit()));
                Py_XDECREF(py_runningrs);
            }
        } Py_XDECREF(py_function);
    }
    Py_XDECREF(py_module);
    Py_XDECREF(py_tuple);
}


void PPScriptExec::pyScript_PixmapVariant(QSize expsize, QPixmap &pixmap, QSize fsize, bool hiq, QVariant curtain){
    if (pixmap.isNull() && !curtain.isNull())
    {
        pyScript_PixmapVariant(pixmap, curtain);
    }
    else if (!pixmap.isNull())
    {
        int fw = fsize.width();
        int fh = fsize.height();
        if (fw < 0 && fh < 0)
        {
            if (hiq)
            {
                pyScript_PilrsizeforPixmap("outer_script", "pixmapresize",pixmap, {expsize.width(), expsize.height()});
            }
            else
            {
                pixmap = pixmap.scaled(expsize,
                                       Qt::IgnoreAspectRatio,
                                       Qt::SmoothTransformation);
            }
        }
        else
        {
            int bastwidth = expsize.width();
            int bestheight = expsize.height();
            double pixw = pixmap.width();
            double pixh = pixmap.height();
            if (fw < 0 && fh >= 0) // 宽无效，高可能有效，则使用窗口高，计算合理宽
            {
                double proportion = pixh / bestheight;
                bastwidth = pixw / proportion;
                if (hiq)
                {
                    pyScript_PilrsizeforPixmap("outer_script", "pixmapresize", pixmap, {bastwidth, bestheight});
                }
                else
                {
                    pixmap = pixmap.scaled(bastwidth, bestheight,
                                           Qt::KeepAspectRatioByExpanding,
                                           Qt::SmoothTransformation);
                }
            }
            else if (fw >= 0 && fh < 0)
            {
                double proportion = pixw / fw;
                bestheight = pixh / proportion;
                if (hiq)
                {
                    pyScript_PilrsizeforPixmap("outer_script", "pixmapresize", pixmap, {bastwidth, bestheight});
                }
                else
                {
                    pixmap = pixmap.scaled(bastwidth, bestheight,
                                           Qt::KeepAspectRatioByExpanding,
                                           Qt::SmoothTransformation);
                }
            }
            else if (fw && fh)
            {
                if (hiq)
                {
                    pyScript_PilrsizeforPixmap("outer_script", "pixmapresize", pixmap, {fsize.width(), fsize.height()});
                }
                else
                {
                    pixmap = pixmap.scaled(fsize,
                                           Qt::IgnoreAspectRatio,
                                           Qt::SmoothTransformation);
                }
            }
        }
    }
}


bool PPScriptExec::pyScript_PixmapVariant(QPixmap &pixmap, QVariant curtain){
    bool byte_pass = false;
    while (true)
    {
        if ((pixmap.isNull() && !curtain.isNull()))
        {
            if (curtain.metaType().id() == QMetaType::QByteArray || byte_pass)
            {
                if (pixmap.loadFromData(QByteArray::fromBase64(curtain.toByteArray())))
                {
                    return true;
                }
                else
                {
                    if (pixmap.loadFromData(curtain.toByteArray()))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else if (curtain.metaType().id() == QMetaType::QString)
            {
                bool load = pixmap.load(curtain.toString());
                if (load)
                {
                    return true;
                }
                else
                {
                    QByteArray imgbyte = Reader::g_reader(curtain.toString());
                    if (imgbyte.isEmpty())
                    {
                        byte_pass = true;
                    }
                    else
                    {
                        curtain.setValue(imgbyte);
                    }
                }
            }
            else if (curtain.metaType().id() == QMetaType::QPixmap)
            {
                QPixmap varpixmap = curtain.value<QPixmap>();
                pixmap.swap(varpixmap);
                return true;
            }
        }
    }
}


bool PPScriptExec::pyScript_PixmapVariant(QVariant curtain){
    QPixmap pixmap;
    return pyScript_PixmapVariant(pixmap, curtain);
}
